/* SCHEME.H */

/** \file scheme.h
    \brief Header info for the TinyScheme compiler
    \ingroup gerbv
*/

#ifndef _SCHEME_H
#define _SCHEME_H

#include <stdio.h>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*
 * Default values for #define'd symbols
 */
#ifndef STANDALONE /* If used as standalone interpreter */
#define STANDALONE 1
#endif

#if !defined(_MSC_VER) && !defined(__MINGW32__)
#define USE_STRCASECMP 1
#define USE_STRLWR     1
#define SCHEME_EXPORT
#else
#define USE_STRCASECMP 0
#define USE_STRLWR     0
#if defined(__MINGW32__)
#define SCHEME_EXPORT
#else
#ifdef _SCHEME_SOURCE
#define SCHEME_EXPORT __declspec(dllexport)
#else
#define SCHEME_EXPORT __declspec(dllimport)
#endif
#endif
#endif

#if USE_NO_FEATURES
#define USE_MATH             0
#define USE_CHAR_CLASSIFIERS 0
#define USE_ASCII_NAMES      0
#define USE_STRING_PORTS     0
#define USE_ERROR_HOOK       0
#define USE_TRACING          0
#define USE_COLON_HOOK       0
#define USE_DL               0
#define USE_PLIST            0
#endif

/*
 * Leave it defined if you want continuations, and also for the Sharp Zaurus.
 * Undefine it if you only care about faster speed and not strict Scheme compatibility.
 */
#define USE_SCHEME_STACK

#if USE_DL
#define USE_INTERFACE 1
#endif

#ifndef USE_MATH /* If math support is needed */
#define USE_MATH 1
#endif

#ifndef USE_CHAR_CLASSIFIERS /* If char classifiers are needed */
#define USE_CHAR_CLASSIFIERS 1
#endif

#ifndef USE_ASCII_NAMES /* If extended escaped characters are needed */
#define USE_ASCII_NAMES 1
#endif

#ifndef USE_STRING_PORTS /* Enable string ports */
#define USE_STRING_PORTS 1
#endif

#ifndef USE_TRACING
#define USE_TRACING 1
#endif

#ifndef USE_PLIST
#define USE_PLIST 0
#endif

/* To force system errors through user-defined error handling (see *error-hook*) */
#ifndef USE_ERROR_HOOK
#define USE_ERROR_HOOK 1
#endif

#ifndef USE_COLON_HOOK /* Enable qualified qualifier */
#define USE_COLON_HOOK 1
#endif

#ifndef USE_STRCASECMP /* stricmp for Unix */
#define USE_STRCASECMP 0
#endif

#ifndef USE_STRLWR
#define USE_STRLWR 1
#endif

#ifndef STDIO_ADDS_CR /* Define if DOS/Windows */
#define STDIO_ADDS_CR 0
#endif

#ifndef INLINE
#define INLINE
#endif

#ifndef USE_INTERFACE
#define USE_INTERFACE 0
#endif

typedef struct scheme scheme;
typedef struct cell*  pointer;

typedef void* (*func_alloc)(size_t);
typedef void (*func_dealloc)(void*);

/* num, for generic arithmetic */
typedef struct num {
    char is_fixnum;

    union {
        long   ivalue;
        double rvalue;
    } value;
} num;

SCHEME_EXPORT scheme* scheme_init_new();
SCHEME_EXPORT scheme* scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
SCHEME_EXPORT int     scheme_init(scheme* sc);
SCHEME_EXPORT int     scheme_init_custom_alloc(scheme* sc, func_alloc, func_dealloc);
SCHEME_EXPORT void    scheme_deinit(scheme* sc);
void                  scheme_set_input_port_file(scheme* sc, FILE* fin);
void                  scheme_set_input_port_string(scheme* sc, char* start, char* past_the_end);
SCHEME_EXPORT void    scheme_set_output_port_file(scheme* sc, FILE* fin);
void                  scheme_set_output_port_string(scheme* sc, char* start, char* past_the_end);
SCHEME_EXPORT void    scheme_load_file(scheme* sc, FILE* fin);
SCHEME_EXPORT void    scheme_load_string(scheme* sc, const char* cmd);
void                  scheme_apply0(scheme* sc, const char* procname);
SCHEME_EXPORT pointer scheme_apply1(scheme* sc, const char* procname, pointer);
void                  scheme_set_external_data(scheme* sc, void* p);
SCHEME_EXPORT void    scheme_define(scheme* sc, pointer env, pointer symbol, pointer value);

typedef pointer (*foreign_func)(scheme*, pointer);

pointer _cons(scheme* sc, pointer a, pointer b, int immutable);
pointer mk_integer(scheme* sc, long num);
pointer mk_real(scheme* sc, double num);
pointer mk_symbol(scheme* sc, const char* name);
pointer gensym(scheme* sc);
pointer mk_string(scheme* sc, const char* str);
pointer mk_counted_string(scheme* sc, const char* str, int len);
pointer mk_character(scheme* sc, int c);
pointer mk_foreign_func(scheme* sc, foreign_func f);
void    putstr(scheme* sc, const char* s);

#if USE_INTERFACE
struct scheme_interface {
    void (*scheme_define)(scheme* sc, pointer env, pointer symbol, pointer value);
    pointer (*cons)(scheme* sc, pointer a, pointer b);
    pointer (*immutable_cons)(scheme* sc, pointer a, pointer b);
    pointer (*mk_integer)(scheme* sc, long num);
    pointer (*mk_real)(scheme* sc, double num);
    pointer (*mk_symbol)(scheme* sc, const char* name);
    pointer (*gensym)(scheme* sc);
    pointer (*mk_string)(scheme* sc, const char* str);
    pointer (*mk_counted_string)(scheme* sc, const char* str, int len);
    pointer (*mk_character)(scheme* sc, int c);
    pointer (*mk_vector)(scheme* sc, int len);
    pointer (*mk_foreign_func)(scheme* sc, foreign_func f);
    void (*putstr)(scheme* sc, const char* s);
    void (*putcharacter)(scheme* sc, int c);

    int (*is_string)(pointer p);
    char* (*string_value)(pointer p);
    int (*is_number)(pointer p);
    num (*nvalue)(pointer p);
    long (*ivalue)(pointer p);
    double (*rvalue)(pointer p);
    int (*is_integer)(pointer p);
    int (*is_real)(pointer p);
    int (*is_character)(pointer p);
    long (*charvalue)(pointer p);
    int (*is_vector)(pointer p);
    long (*vector_length)(pointer vec);
    void (*fill_vector)(pointer vec, pointer elem);
    pointer (*vector_elem)(pointer vec, int ielem);
    pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel);
    int (*is_port)(pointer p);

    int (*is_pair)(pointer p);
    pointer (*pair_car)(pointer p);
    pointer (*pair_cdr)(pointer p);
    pointer (*set_car)(pointer p, pointer q);
    pointer (*set_cdr)(pointer p, pointer q);

    int (*is_symbol)(pointer p);
    char* (*symname)(pointer p);

    int (*is_syntax)(pointer p);
    int (*is_proc)(pointer p);
    int (*is_foreign)(pointer p);
    char* (*syntaxname)(pointer p);
    int (*is_closure)(pointer p);
    int (*is_macro)(pointer p);
    pointer (*closure_code)(pointer p);
    pointer (*closure_env)(pointer p);

    int (*is_continuation)(pointer p);
    int (*is_promise)(pointer p);
    int (*is_environment)(pointer p);
    int (*is_immutable)(pointer p);
    void (*setimmutable)(pointer p);
    void (*load_file)(scheme* sc, FILE* fin);
    void (*load_string)(scheme* sc, const char* input);
};
#endif

#endif
